def partitions(n):
    if n <= 0:
        raise ValueError("Argument must be at least 1.")

    partition = dict()                              # will map the part value to its number of occurrences ie 4:1 2:2 is
                                                    #   4 + 2 + 2
    part_values = [n]                               # will contain the distinct elements of the partition ie [4,2]
    partition[n] = 1                                # start with the number itself as the partition
    yield partition

    while part_values != [1]:                       # the last partition to be returned will be all ones, at this point
                                                    #   we stop
        if part_values[-1] == 1:                    # if have ones in the last iteration, they cannot be further
                                                    #   decomposed, so count them and remove 1 from the part values
            part_values.remove(1)                   # we need to know the number of 1's because it will alter the value
            num_ones = partition.pop(1)             #   we intend to reuse
        else:
            num_ones = 0

        reuse = part_values[-1]                     # in every iteration, we will be altering the last value in the list
                                                    #   reducing it until it becomes all 1's
        partition[reuse] -= 1                       # since we are reducing the last number in the list, we must reduce
                                                    #   its count in the partition 4:2 -> 4:1, 3:1, 1:1.. 4:2 is now 4:1
        if partition[reuse] == 0:                   # if the reduction in count resulted in a count of 0, its not in the
                                                    #   partition anymore 7:1, 1:1 -> 6:1, 2: 1... 7:1 becomes 7:0
            del partition[reuse]
            part_values.remove(reuse)               # obviously, it can't be in the part values anymore
        new_part_value = reuse - 1                  # the "reduction" we've been referring to
        reuse += num_ones                           # at the beginning, we said we needed to keep track of the number
                                                    #   of 1's used, here is why.. if you are 7:1, 1:1 -> 6:1, 2:1,
                                                    # you need to add 1 to 7 so that when you divide it by 6, you get
                                                    #   the correct remainder
        q, r = divmod(reuse, new_part_value)        # find the new values to add to the list, ie 6 and 2
        partition[new_part_value] = q
        part_values.append(new_part_value)
        if r:                                       # if there is a remainder, you must also add that to the list
            partition[r] = 1
            part_values.append(r)

        yield partition

if __name__ == "__main__":
    for x in partitions(10):
        print (x)